﻿# -*- coding: utf-8 -*-
#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import csv
import urllib
import random
import datetime
import locale
from google.appengine.ext.webapp import template

from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util

from google.appengine.ext import db
from google.appengine.api import images

import regras
import settings
from modelos import *

class MainHandler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'home.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
            
        participantes = [p for p in Participante.all().filter("owner =", user)]
        for p in participantes:
            p.update_from_ranking(bolao)
            
        msg = self.request.get("msg")
        
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'participantes': participantes,
            'eh_convidado': bolao.eh_convidado(user),
            'bolao': bolao,
            'msg': msg,
        }        
        self.response.out.write(template.render(path, template_values))

class ErrorMsgHandler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'errormsg.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
            
        participantes = [p for p in Participante.all().filter("owner =", user)]
        msg = self.request.get("msg")
        
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'participantes': participantes,
            'eh_convidado': bolao.eh_convidado(user),
            'bolao': bolao,
            'msg': msg,
        }        
        self.response.out.write(template.render(path, template_values))

class ParticipanteHandler(webapp.RequestHandler):
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return

        logout_url = users.create_logout_url("/")
        participante = Participante.get(self.request.get("key"))
        bolao = Bolao.all().get()
        participante.update_from_ranking(bolao)
        
        grupos_a_mostrar = bolao.grupos_a_mostrar()
        if user == participante.owner and bolao.em_palpites():
            grupos_a_mostrar = bolao.grupos_a_editar() + grupos_a_mostrar

        # nova tentativa para pagina de participante
        quadros = participante.gera_quadros_jogos(grupos_a_mostrar)
        
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'participante': participante,
            'eh_convidado': bolao.eh_convidado(user),
            'exibe_evolucao': bolao.fase.num >= 2,
            'grupos': grupos_a_mostrar,
            'msg': self.request.get("msg"),
            'bolao': bolao,
            'quadros': quadros,
            }
        path = os.path.join(os.path.dirname(__file__), 'participante.html')
        self.response.out.write(template.render(path, template_values))            
            
class AntigoRankingHandler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'ranking.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
            
        participantes = [p for p in Participante.all()]
        participantes.sort(key=lambda participante: participante.detalhamento_pontos_fase1(), reverse=True)
        
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'participantes': participantes,
            'eh_convidado': bolao.eh_convidado(user),
            'bolao': bolao,
            }        
        self.response.out.write(template.render(path, template_values))

class RankingHandler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'novoranking.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
        
        class LinhaRanking:
            pass
        
        ranking = []
        for i in range(len(bolao.ranking_participantes)):
            linha = LinhaRanking()
            linha.pontos = [int(e) for e in bolao.ranking_pontos[i].split("|")]
            linha.posicao = bolao.ranking_posicoes[i]
            linha.participante = db.get(bolao.ranking_participantes[i])
            posicao_anterior = linha.participante.evolucao_ranking1[bolao.num_jogos_ocorridos-1]
            
            # TODO: extract method
            delta_ranking = linha.posicao - posicao_anterior
            if delta_ranking > 0:
                linha.setas = min(abs(delta_ranking),settings.MAX_SETAS)*[-1]
            elif delta_ranking < 0:
                linha.setas = min(abs(delta_ranking),settings.MAX_SETAS)*[1]
            else:
                linha.setas = [0]
            if abs(delta_ranking) >= 5:
                linha.evolucao = "("+ str(abs(delta_ranking)) +")"
            else:
                linha.evolucao = ""
            ranking.append(linha)
                
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'ranking': ranking,
            'eh_convidado': bolao.eh_convidado(user),
            'bolao': bolao,
            'msg': "",
            }        
        self.response.out.write(template.render(path, template_values))

class SecacaoHandler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'secacao.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
        
        class LinhaTabela:
            pass
        
        jogo = Jogo.gql("WHERE ocorreu=False ORDER BY datahora").get()
        tabela = []
        for i in range(len(bolao.ranking_participantes)):
            linha = LinhaTabela()
            linha.posicao = bolao.ranking_posicoes[i]
            linha.participante = db.get(bolao.ranking_participantes[i])
            linha.score1 = linha.participante.scores1[jogo.num-1]
            linha.score2 = linha.participante.scores2[jogo.num-1]
            if bolao.em_palpites():
                linha.score1 = "?"
                linha.score2 = "?"
            
            tabela.append(linha)
            
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'tabela': tabela,
            'eh_convidado': bolao.eh_convidado(user),
            'bolao': bolao,
            'msg': "",
            'proximo_jogo': jogo,
            }        
        self.response.out.write(template.render(path, template_values))


class RankingFase2Handler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'novoranking2.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
        
        class LinhaRanking:
            pass
        
        ranking = []
        for i in range(len(bolao.ranking_participantes_2)):
            linha = LinhaRanking()
            linha.pontos = [int(e) for e in bolao.ranking_pontos_2[i].split("|")]
            linha.posicao = bolao.ranking_posicoes_2[i]
            linha.participante = db.get(bolao.ranking_participantes_2[i])
            posicao_anterior = linha.participante.evolucao_ranking2[bolao.num_jogos_ocorridos-48-1]
            
            # TODO: extract method
            delta_ranking = linha.posicao - posicao_anterior
            if delta_ranking > 0:
                linha.setas = min(abs(delta_ranking),settings.MAX_SETAS)*[-1]
            elif delta_ranking < 0:
                linha.setas = min(abs(delta_ranking),settings.MAX_SETAS)*[1]
            else:
                linha.setas = [0]
            if abs(delta_ranking) >= 5:
                linha.evolucao = "("+ str(abs(delta_ranking)) +")"
            else:
                linha.evolucao = ""
            ranking.append(linha)
            
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'ranking': ranking,
            'eh_convidado': bolao.eh_convidado(user),
            'bolao': bolao,
            'msg': "",
            }        
        self.response.out.write(template.render(path, template_values))
   
class ParticipantesHandler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'participantes.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return

        participantes = [p for p in Participante.all()]
        participantes.sort(key=lambda participante: participante.nome)
        num_participantes = len(participantes)
        num_participantes_confirmados = len([p for p in participantes if p.status == "pago"])
        total_bolao = 50.0*num_participantes_confirmados
        valor_bolao = (total_bolao, 0.75*total_bolao, 0.25*total_bolao)
        
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'participantes': participantes,
            'num_participantes': num_participantes,
            'valor_bolao': valor_bolao,
            'num_participantes_confirmados': num_participantes_confirmados,
            'eh_convidado': bolao.eh_convidado(user),
            'bolao': bolao,
            }        
        self.response.out.write(template.render(path, template_values))

class PalpitesHandler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'palpites.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return

        participantes = [p for p in Participante.all()]
        participantes.sort(key=lambda participante: participante.nome)
        
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'eh_convidado': bolao.eh_convidado(user),
            'participantes': participantes,
            'jogos': [jogo for jogo in Jogo.all().order("num")],
            'bolao': bolao,
            }        
        self.response.out.write(template.render(path, template_values))

class Evolucao1Handler(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'evolucao1.html')
        logout_url = users.create_logout_url("/")
        
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
            
        
        participante = db.get(self.request.get("key"))
        dados_participante = [str(100-(100*pos/123.)) for pos in participante.evolucao_ranking1]
        dados_ranking2 = 48*["_"] + [str(100-(100*pos/123.)) for pos in participante.evolucao_ranking2]
        
        chart = []
        #chart.append("chtt=Evolução de Alguém")
        chart.append("cht=lc")
        chart.append("chco=0000ff,ff0000")
        chart.append("chs=600x400")
        chart.append("chxt=y,x,r")
        chart.append("chxr=0,123,0,10|1,0," + str(bolao.num_jogos_ocorridos) + ",4")
        chart.append("chxp=2,100,%s,%s" % (dados_participante[-1],dados_ranking2[-1]) )
        chart.append("chxl=2:|1|%s|%s" % (str(participante.evolucao_ranking1[-1]),str(participante.evolucao_ranking2[-1])))
        if self.request.get("fase") == "2":
            chart.append("chd=t:" + ",".join(dados_participante) + "|" + ",".join(dados_ranking2))
        else:
            chart.append("chd=t:" + ",".join(dados_participante))
            
        chart.append("chxs=0,000000,10,0,lt|1,000000,10,1,lt")
        chart.append("chf=c,ls,90,dddddd,.50,FFFF00,0.30,9ACD32,0.20")
        chart.append("chm=o,0000ff,0,-1,7.0|o,ffffff,0,-1,5.0|o,888888,1,-1,7.0|o,ffffff,1,-1,5.0")

        template_values = {
            'logout_url': logout_url,
            'chart_code': "&".join(chart),
            'user': user,
            'participante': participante,
            'eh_convidado': bolao.eh_convidado(user),
            'jogos': [jogo for jogo in Jogo.all().order("num")],
            'bolao': bolao,
            }        
        self.response.out.write(template.render(path, template_values))

        
class ParticipantesCSVHandler(webapp.RequestHandler):
    def get(self):
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
        
        participantes = [p for p in Participante.all().order("nome")]
        separador_scores = self.request.get("sep")
        if not separador_scores:
            separador_scores = "x"              

        # TODO: se jogo_final e jogo_inicial so sao usados aqui, colocar dados direto na tabela e
        # evitar a logica abaixo
        if bolao.em_palpites():
            ultimo_jogo = bolao.fase.jogo_inicial - 1
        else:
            ultimo_jogo = bolao.fase.jogo_final
        ids_jogos = ["j%d" % num for num in xrange(1, ultimo_jogo+1)]
        linhas_palpites = ["Nome,email," + ",".join(ids_jogos)]
        
        for p in participantes:
            palpites = []
            for num in range(1, bolao.fase.jogo_final+1 ):
                palpites.append( "%d%s%d" %(p.scores1[num-1], separador_scores, p.scores2[num-1]) )
            linhas_palpites.append("%s,%s,%s" % (p.nome, p.owner.email(), ",".join(palpites)))
        
        resposta = "\r\n".join(linhas_palpites)
        nome_arquivo = "palpites %s.csv" % datetime.datetime.now().strftime("%Y-%b-%d %H:%M:%S")
        self.response.headers.add_header('content-disposition', 'attachment', filename=nome_arquivo)
        self.response.out.write(resposta)

class JogosCSVHandler(webapp.RequestHandler):
    def get(self):
        # TODO: 
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
        
        jogos = [j for j in Jogo.all().order("num")]
        linhas_jogos = ["Número,Data e Hora(Brasil),Local,Ocorreu,País 1(sigla),País 2(sigla),Grupo,Fase,Score 1,Score 2"]
        
        for jogo in jogos:
            dados = []
            dados.append(str(jogo.num))
            dados.append(str(jogo.datahora))
            dados.append(str(jogo.local))
            dados.append(str(jogo.ocorreu))
            dados.append(str(jogo.pais1))
            dados.append(str(jogo.pais2))
            dados.append(str(jogo.grupo))
            dados.append(str(jogo.fase))
            dados.append(str(jogo.score1))
            dados.append(str(jogo.score2))
            linhas_jogos.append(",".join(dados))
        
        resposta = "\r\n".join(linhas_jogos)
        nome_arquivo = "jogos %s.csv" % datetime.datetime.now().strftime("%Y-%b-%d %H:%M:%S")
        self.response.headers.add_header('content-disposition', 'attachment', filename=nome_arquivo)
        self.response.out.write(resposta)

class AdicionaParticipanteHandler(webapp.RequestHandler):
    def post(self):
        bolao = Bolao.all().get()
        user = users.get_current_user()
        if not user:
            # TODO: log, usuario nao convidado tentou cadastrar participante
            msg = "usuario nao convidado tentou cadastrar participante"
            self.redirect("/msgerro?msg=%s" % msg)
            return
        
        nome = self.request.get("nome")
        if bolao.fase.id == "adesao" and self.eh_valido(nome) and bolao.eh_convidado(user):
            p = Participante()
            p.nome = nome
            p.owner = users.get_current_user()
            p.put()
            self.redirect("/")
        else:
            # TODO: log
            # TODO: entender por que acentos nao aparecem
            msg = "Opa! Impossivel criar participante. Contacte a coordenacao do bolao."
            self.redirect("/?msg=%s" % msg)
    
    def eh_valido(self, nome):
        return nome != "" and nome not in [p.nome for p in Participante.all()]

class RegrasHandler(webapp.RequestHandler):
    def get(self):
        logout_url = users.create_logout_url("/")
        user = users.get_current_user()
        bolao = Bolao.all().get()
                
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'eh_convidado': True,
            'bolao': bolao,
        }
        path = os.path.join(os.path.dirname(__file__), 'regras.html')
        self.response.out.write(template.render(path, template_values))

class EditaPalpitesHandler(webapp.RequestHandler):
    def post(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
            
        bolao = Bolao.all().get()
        if not bolao.eh_convidado(user):
            # TODO: usuario nao convidado tenta gravar palpites (fazer log!)
            msg = "usuario nao convidado tenta gravar palpites"
            self.redirect("/msgerro?msg=%s" % msg)
            return

        participante = Participante.get(self.request.get("key"))
        if user != participante.owner or not bolao.em_palpites():
            # TODO: usuario tenta gravar palpites fora do periodo de edição (log) ou
            # TODO: gravar palpites de participante que nao eh dele (log)
            msg = "fora do periodo de edicao OU participante nao eh do usuario logado"
            self.redirect("/msgerro?msg=%s" % msg)
            return
            
        dados_validos = True
        jogos = Jogo.all().filter("fase =", bolao.fase_copa())
        for jogo in jogos:
            score1 = self.request.get("j%d_sc1" % jogo.num)
            score2 = self.request.get("j%d_sc2" % jogo.num)
            if self.score_valido(score1, score2):
                participante.scores1[jogo.num-1] = int(score1)
                participante.scores2[jogo.num-1] = int(score2)
            else:
                dados_validos = False
        
        if not dados_validos:
            # TODO: usuario tentou gravar palpites invalidos: form errado? exploit? (log)
            msg = "usuario tentou gravar palpites invalidos: form errado? exploit?"
            self.redirect("/msgerro?msg=%s" % msg)
            return
            
        participante.put()
        msg = "Palpites gravados com sucesso."
        #TODO: log de que o usuário gravou seus dados
        #TODO: que tal gravar info no próprio participante
        self.redirect("/?msg=%s" % msg)                

    def score_valido(self, sc1, sc2):
        return sc1.strip().isdigit() and sc2.strip().isdigit()
                
    def get(self):
        bolao = Bolao.all().get()
        user = users.get_current_user()
        key = self.request.get("key")
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
        
        if not bolao.em_palpites():
            self.redirect("/participante?key="+key)
            return
            
        participante = Participante.get(key)
        if user != participante.owner:
            msg = "Usuario tenta editar palpites de participante que nao eh dele"
            self.redirect("/msgerro?msg=%s" % msg)
            return

        logout_url = users.create_logout_url("/")
        randomize = self.request.get("randomize") == "1"
        quadros = participante.gera_quadros_jogos(bolao.grupos_a_editar(), randomize)
        
        template_values = {
            'logout_url': logout_url,
            'participante': participante,
            'user': user,
            'eh_convidado': bolao.eh_convidado(user),
            'bolao': bolao,
            'grupos': bolao.grupos_a_editar(),
            'quadros': quadros,
            }
        path = os.path.join(os.path.dirname(__file__), 'editapalpites.html')
        self.response.out.write(template.render(path, template_values))
        
class ExcluiParticipanteHandler(webapp.RequestHandler):
    def post(self):
        user = users.get_current_user()
        key = self.request.get("key")
        participante = db.get(key)
        bolao = Bolao.all().get()
        # TODO: msgerro e log se user nao eh dono do participante a deletar
        if user == participante.owner and bolao.fase.id == "adesao":
            participante.delete()
            self.redirect("/")
        else:
            msg = "user nao eh dono do participante a deletar"
            self.redirect("/msgerro?msg=%s" % msg)
        
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return

        bolao = Bolao.all().get()
        key = self.request.get("key")
        participante = Participante.get(key)
        
        if bolao.fase.id != "adesao" or user != participante.owner:
            # TODO: log
            msg = "fora de fase de adesao OU usuario nao eh dono do participante"
            self.redirect("/msgerro?msg=%s" % msg)
            return

        logout_url = users.create_logout_url("/")
        template_values = {
            'logout_url': logout_url,
            'user': user,
            'eh_convidado': bolao.eh_convidado(user),
            'participante': participante,
            }
        path = os.path.join(os.path.dirname(__file__), 'excluiparticipante.html')
        self.response.out.write(template.render(path, template_values))
        

class FotoParticipanteHandler(webapp.RequestHandler):
    def get(self):
        participante = db.get(self.request.get("key"))
        if participante.avatar:
            self.response.headers['Content-Type'] = "image/png"
            self.response.out.write(participante.avatar)
        else:
            self.error(404)
    
    def post(self):
        user = users.get_current_user()
        key = self.request.get("key")
        participante = db.get(key)
        
        # TODO: msgerro e log se user nao eh dono do participante 
        if not (user == participante.owner or users.is_current_user_admin()):
            msg = "Erro: o participante indicado não é seu."
            self.redirect("/participante?key=%s&msg=%s" % (str(participante.key()),  msg) )
            return
        
        arquivo = self.request.get("arquivo")
        if len(arquivo) >= 1048576:
            msg = "Arquivo grande demais!!!"
            self.redirect("/participante?key=%s&msg=%s" % (str(participante.key()),msg) )
            return
        
        # manipulacao do arquivo enviado
        img = images.Image(arquivo)
        lx, ty = 0.0, 0.0
        rx = img.height / float(max(img.height, img.width))
        by = img.width / float(max(img.height, img.width))
        img.crop(lx, ty, rx, by)
        img.resize(width=100, height=100)
        img.im_feeling_lucky()
        thumbnail = img.execute_transforms(output_encoding=images.JPEG)
        
        # TODO: testar se dado passado eh de fato uma imagem e, se eh de tamanho apropriado
        participante.avatar = thumbnail
        participante.put()
        self.redirect("/participante?key=%s" % str(participante.key()) )

class EditaFotoHandler(webapp.RequestHandler):
    def get(self):
        user = users.get_current_user()
        key = self.request.get("key")
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
        
        participante = Participante.get(key)
        if user != participante.owner:
            msg = "Usuario tenta editar foto de participante que nao eh dele"
            self.redirect("/msgerro?msg=%s" % msg)
            return
        
        logout_url = users.create_logout_url("/")
        bolao = Bolao.all().get()
        
        template_values = {
            'logout_url': logout_url,
            'bolao': bolao,
            'eh_convidado': bolao.eh_convidado(user),
            'participante': participante,
            'user': user,
            }
        
        path = os.path.join(os.path.dirname(__file__), 'editafoto.html')
        self.response.out.write(template.render(path, template_values))

def main():
    application = webapp.WSGIApplication([
        ('/', MainHandler),
        ('/adicionaparticipante', AdicionaParticipanteHandler),
        ('/editapalpites', EditaPalpitesHandler),
        ('/excluiparticipante', ExcluiParticipanteHandler),
        ('/evolucao1', Evolucao1Handler),
        ('/fotoparticipante', FotoParticipanteHandler),
        ('/editafoto', EditaFotoHandler),
        ('/jogos.csv', JogosCSVHandler),
        ('/msgerro', ErrorMsgHandler),
        ('/ranking', RankingHandler),
        ('/ranking2', RankingFase2Handler),
        ('/palpites', PalpitesHandler),
        ('/palpites.csv', ParticipantesCSVHandler),
        ('/secacao', SecacaoHandler),
        ('/participante', ParticipanteHandler),
        ('/participantes', ParticipantesHandler),
        ('/antigoranking', AntigoRankingHandler),
        ('/regras', RegrasHandler),
        ],
        debug=True)
    util.run_wsgi_app(application)


if __name__ == '__main__':
    main()